import utilsServer from "@/api/services/utilsServer";
import utils from "@/utils/utils";
import { Color } from "three";


//轮廓图生成对象 输出的图片尺寸是 1024*1024
class OutlineGenerate {
  constructor() {

  }

  canvas = (() => {
    const canvas = document.createElement("canvas");
    canvas.width = 1024;
    canvas.height = 1024;
    return canvas;
  })();

  ctx = this.canvas.getContext("2d")!;

  // 生成轮廓外遮罩图
  generateOulineMark(svgurl: string) {
    return new Promise<string>((resolve, reject) => {
      fetch(svgurl)
        .then(response => response.text())
        .then(svgText => {
          const color = new Color();
          const colors = svgText.match(/#[a-zA-Z\d]{6}/g) || [];
          for (let c of colors) {
            color.set(c);
            if (color.r > (color.g + 0.5) && color.r > (color.b + 0.5)) { // 不显示红色的线
              svgText = svgText.replaceAll(c, `${c};display: none;`);
            } else if (color.r < 0.1 && color.g < 0.1 && color.b < 0.1) { // 其他的线都改成白色
              svgText = svgText.replaceAll(c, `${c};fill:#ffffff;`);
            }
          }

          //路径转多边形
          // 正则表达式模式，用于匹配路径数据
          const pathRegex = / d="([^"]+)"/;

          // 提取路径数据
          const match = svgText.match(pathRegex) || [];
          if (match.length) {
            let pathData = match[1] || "";
            const Mpath = pathData.split("M");
            svgText = svgText.replace(pathData, `M${Mpath[1] || ""}`);
          }
          // 创建 Blob 对象
          const blob = new Blob([svgText], { type: 'image/svg+xml' });
          // 创建临时 URL 并设置给 img.src
          const url = URL.createObjectURL(blob);

          const img = document.createElement("img");
          img.crossOrigin = "anonymous";
          img.onload = async () => {
            this.ctx.fillStyle = "#ffffff";
            this.ctx.globalCompositeOperation = "copy";
            this.ctx.globalAlpha = 1;
            this.ctx.fillRect(0, 0, 1024, 1024);
            this.ctx.globalCompositeOperation = "destination-out";
            const { naturalWidth, naturalHeight } = img;
            const scale = 1024 / Math.max(naturalWidth, naturalHeight);
            const offsetX = 512 - naturalWidth * scale / 2;
            const offsetY = 512 - naturalHeight * scale / 2;
            this.ctx.drawImage(img, offsetX, offsetY, naturalWidth * scale, naturalHeight * scale);

            // 导出base64 然后转为file对象 不是下载file
            const base64 = this.canvas.toDataURL("image/png");
            const file = utils.base64ToFile(base64, 'test.png');
            const uploadUrl = await utilsServer.uploadOss(file);

            resolve(uploadUrl);
          }
          img.src = url;
        });
    });
  }

  // 生成设计图遮罩
  generateDesignMark(
    svgurl: string,
    markRect: { x: number, y: number, width: number, height: number },
    clipMarkRect: { x: number, y: number, width: number, height: number }
  ) {
    return new Promise<string>((resolve, reject) => {
      fetch(svgurl)
        .then(response => response.text())
        .then(svgText => {
          const color = new Color();
          const colors = svgText.match(/#[a-zA-Z\d]{6}/g) || [];
          for (let c of colors) {
            color.set(c);
            if (color.r > (color.g + 0.5) && color.r > (color.b + 0.5)) { // 不显示红色的线
              svgText = svgText.replaceAll(c, `${c};display: none;`);
            } else if (color.r < 0.1 && color.g < 0.1 && color.b < 0.1) { // 其他的线都改成白色
              svgText = svgText.replaceAll(c, `${c};fill:#ffffff;`);
            }
          }

          //路径转多边形
          // 正则表达式模式，用于匹配路径数据
          const pathRegex = / d="([^"]+)"/;

          // 提取路径数据
          const match = svgText.match(pathRegex) || [];
          if (match.length) {
            let pathData = match[1] || "";
            const Mpath = pathData.split("M");
            svgText = svgText.replace(pathData, `M${Mpath[1] || ""}`);
          }
          // 创建 Blob 对象
          const blob = new Blob([svgText], { type: 'image/svg+xml' });
          // 创建临时 URL 并设置给 img.src
          const url = URL.createObjectURL(blob);

          const img = document.createElement("img");
          img.crossOrigin = "anonymous";
          img.onload = async () => {
            // 部位的边长
            const sideLength = Math.max(img.naturalWidth, img.naturalHeight) * (1 / 2.8346);

            this.ctx.clearRect(0, 0, 1024, 1024);
            this.ctx.fillStyle = "#ffffff";
            this.ctx.globalCompositeOperation = "copy";
            this.ctx.globalAlpha = 1;
            this.ctx.fillRect(
              markRect.x / sideLength * 1024,
              markRect.y / sideLength * 1024,
              markRect.width / sideLength * 1024,
              markRect.height / sideLength * 1024
            );

            const { naturalWidth, naturalHeight } = img;
            const scale = 1024 / Math.max(naturalWidth, naturalHeight);
            const offsetX = 512 - naturalWidth * scale / 2;
            const offsetY = 512 - naturalHeight * scale / 2;
            this.ctx.globalCompositeOperation = "source-in";
            this.ctx.drawImage(img, offsetX, offsetY, naturalWidth * scale, naturalHeight * scale);

            this.ctx.clearRect(
              clipMarkRect.x / sideLength * 1024,
              clipMarkRect.y / sideLength * 1024,
              clipMarkRect.width / sideLength * 1024,
              clipMarkRect.height / sideLength * 1024
            );

            this.ctx.fillStyle = "#ffffff";
            this.ctx.globalCompositeOperation = "source-out";
            this.ctx.globalAlpha = 1;
            this.ctx.fillRect(0, 0, 1024, 1024);

            // 导出base64 然后转为file对象 不是下载file
            const base64 = this.canvas.toDataURL("image/png");
            const file = utils.base64ToFile(base64, 'test.png');
            const uploadUrl = await utilsServer.uploadOss(file);
            resolve(uploadUrl);
          }
          img.src = url;
        });
    });
  }

  // 生成板片轮廓虚线图(不带局部印的虚线框)
  generateOutlineDash(
    svgurl: string,
    markRect: { x: number, y: number, width: number, height: number },
    clipMarkRect: { x: number, y: number, width: number, height: number }
  ) {
    return new Promise<string>((resolve, reject) => {
      const img = document.createElement("img");
      img.crossOrigin = "anonymous";
      img.onload = async () => {
        // 部位的边长
        const sideLength = Math.max(img.naturalWidth, img.naturalHeight) * (1 / 2.8346);

        const { naturalWidth, naturalHeight } = img;
        const scale = 1024 / Math.max(naturalWidth, naturalHeight);
        const offsetX = 512 - naturalWidth * scale / 2;
        const offsetY = 512 - naturalHeight * scale / 2;
        this.ctx.clearRect(0, 0, 1024, 1024);
        this.ctx.globalCompositeOperation = "copy";
        this.ctx.globalAlpha = 1;
        this.ctx.drawImage(img, offsetX, offsetY, naturalWidth * scale, naturalHeight * scale);
        const base64 = this.canvas.toDataURL("image/png");
        const file = utils.base64ToFile(base64, 'test.png');
        const uploadUrl = await utilsServer.uploadOss(file);
        resolve(uploadUrl);
      }
      img.src = svgurl;
    });

  }

  // 生成板片的打印区域虚线图
  generatePrintlineDash(
    svgurl: string,
    markRect: { x: number, y: number, width: number, height: number },
    clipMarkRect: { x: number, y: number, width: number, height: number }
  ) {
    return new Promise<string>((resolve, reject) => {
      const img = document.createElement("img");
      img.crossOrigin = "anonymous";
      img.onload = async () => {
        // 部位的边长
        const sideLength = Math.max(img.naturalWidth, img.naturalHeight) * (1 / 2.8346);
        this.ctx.clearRect(0, 0, 1024, 1024);
        //如果是局部打印的话 就绘制一个红白相间的打印框
        if (markRect.x > 0 && markRect.y > 0) {
          this.ctx.save();
          this.ctx.globalCompositeOperation = "source-over";
          this.ctx.resetTransform();
          this.ctx.strokeStyle = "#cccccc";
          this.ctx.lineWidth = 3;
          this.ctx.globalAlpha = 1;
          this.ctx.setLineDash([10, 6]);
          this.ctx.beginPath();
          this.ctx.moveTo((markRect.x - 2) / sideLength * 1024, (markRect.y - 2) / sideLength * 1024);
          this.ctx.lineTo((markRect.x + markRect.width + 2) / sideLength * 1024, (markRect.y - 2) / sideLength * 1024);
          this.ctx.lineTo((markRect.x + markRect.width + 2) / sideLength * 1024, (markRect.y + markRect.height + 2) / sideLength * 1024);
          this.ctx.lineTo((markRect.x - 2) / sideLength * 1024, (markRect.y + markRect.height + 2) / sideLength * 1024);
          this.ctx.closePath();
          this.ctx.stroke();
          this.ctx.restore();

          this.ctx.save();
          this.ctx.globalCompositeOperation = "source-over";
          this.ctx.resetTransform();
          this.ctx.strokeStyle = "#ff0000";
          this.ctx.lineWidth = 1;
          this.ctx.globalAlpha = 1;
          this.ctx.setLineDash([8, 8]);
          this.ctx.beginPath();
          this.ctx.moveTo((markRect.x - 2) / sideLength * 1024, (markRect.y - 2) / sideLength * 1024);
          this.ctx.lineTo((markRect.x + markRect.width + 2) / sideLength * 1024, (markRect.y - 2) / sideLength * 1024);
          this.ctx.lineTo((markRect.x + markRect.width + 2) / sideLength * 1024, (markRect.y + markRect.height + 2) / sideLength * 1024);
          this.ctx.lineTo((markRect.x - 2) / sideLength * 1024, (markRect.y + markRect.height + 2) / sideLength * 1024);
          this.ctx.closePath();
          this.ctx.stroke();
          this.ctx.restore();
        }

        if (clipMarkRect.width > 0 && clipMarkRect.height > 0) {
          this.ctx.save();
          this.ctx.globalCompositeOperation = "source-over";
          this.ctx.resetTransform();
          this.ctx.strokeStyle = "#cccccc";
          this.ctx.lineWidth = 3;
          this.ctx.globalAlpha = 1;
          this.ctx.setLineDash([10, 6]);
          this.ctx.beginPath();
          this.ctx.moveTo((clipMarkRect.x + 2) / sideLength * 1024, (clipMarkRect.y + 2) / sideLength * 1024);
          this.ctx.lineTo((clipMarkRect.x + clipMarkRect.width - 2) / sideLength * 1024, (clipMarkRect.y + 2) / sideLength * 1024);
          this.ctx.lineTo((clipMarkRect.x + clipMarkRect.width - 2) / sideLength * 1024, (clipMarkRect.y + clipMarkRect.height - 2) / sideLength * 1024);
          this.ctx.lineTo((clipMarkRect.x + 2) / sideLength * 1024, (clipMarkRect.y + clipMarkRect.height - 2) / sideLength * 1024);
          this.ctx.closePath();
          this.ctx.stroke();
          this.ctx.restore();

          this.ctx.save();
          this.ctx.globalCompositeOperation = "source-over";
          this.ctx.resetTransform();
          this.ctx.strokeStyle = "#ff0000";
          this.ctx.lineWidth = 1;
          this.ctx.globalAlpha = 1;
          this.ctx.setLineDash([8, 8]);
          this.ctx.beginPath();
          this.ctx.moveTo((clipMarkRect.x + 2) / sideLength * 1024, (clipMarkRect.y + 2) / sideLength * 1024);
          this.ctx.lineTo((clipMarkRect.x + clipMarkRect.width - 2) / sideLength * 1024, (clipMarkRect.y + 2) / sideLength * 1024);
          this.ctx.lineTo((clipMarkRect.x + clipMarkRect.width - 2) / sideLength * 1024, (clipMarkRect.y + clipMarkRect.height - 2) / sideLength * 1024);
          this.ctx.lineTo((clipMarkRect.x + 2) / sideLength * 1024, (clipMarkRect.y + clipMarkRect.height - 2) / sideLength * 1024);
          this.ctx.closePath();
          this.ctx.stroke();
          this.ctx.restore();
        }

        const base64 = this.canvas.toDataURL("image/png");
        const file = utils.base64ToFile(base64, 'test.png');
        const uploadUrl = await utilsServer.uploadOss(file);
        resolve(uploadUrl);
      }
      img.src = svgurl;
    });

  }

  //生成各种轮廓图
  async generate(
    svgurl: string,
    markRect: { x: number, y: number, width: number, height: number },
    clipMarkRect: { x: number, y: number, width: number, height: number }
  ) {
    const [
      oulineMark,
      designMark,
      outlineDash,
      printlineDash
    ] = await Promise.all([
      this.generateOulineMark(svgurl),
      this.generateDesignMark(svgurl, markRect, clipMarkRect),
      this.generateOutlineDash(svgurl, markRect, clipMarkRect),
      this.generatePrintlineDash(svgurl, markRect, clipMarkRect)
    ]);

    return { oulineMark, designMark, outlineDash };
  }


}


const outlineGenerate = new OutlineGenerate();

export default outlineGenerate;
